using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UObject = UnityEngine.Object;//UnityEngine.Object和System.object引用不明确
public class ResourceManager : MonoBehaviour
{
    internal class BundleInfo
    {
        public string AssetsName;
        public string BundleName;
        public List<string> Dependences;
    }
    internal class BundleData
    {
        public AssetBundle Bundle;
        //引用计数
        public int Count;
        public BundleData(AssetBundle ab)
        {
            Bundle = ab;
            Count = 1;
        }
    }
    //存放Bundle信息集合(AssetsName为key)
    private Dictionary<string, BundleInfo> m_BundleInfos = new Dictionary<string, BundleInfo>();
    //存放Bundle资源，加载的bundle存在这里
    private Dictionary<string, BundleData> m_AssetBundles = new Dictionary<string, BundleData>();
    public void ParseVersionFile()
    {//解析版本文件
        //版本文件的路径
        string url = Path.Combine(PathUtil.BundleResourcePath, AppConst.FileListName);
        string[] data = File.ReadAllLines(url);

        //去除版本号
        string[] newFiles = new string[data.Length - 1];
        // 复制原数组中的元素到新数组，除了最后一个
        Array.Copy(data, newFiles, newFiles.Length);
        data = newFiles;

        //解析文件信息
        for (int i = 0; i < data.Length; i++)//按排
        {
            BundleInfo bundleInfo = new BundleInfo();
            string[] trueData = data[i].Split("$");
            string[] info = trueData[0].Split('|');//通过|分割
            bundleInfo.AssetsName = info[0];

            bundleInfo.BundleName = info[1];
            bundleInfo.Dependences = new List<string>(info.Length - 2);
            for (int j = 2; j < info.Length; j++)
            {
                bundleInfo.Dependences.Add(info[j]);
            }
            m_BundleInfos.Add(bundleInfo.AssetsName, bundleInfo);

            if (info[0].IndexOf("LuaScripts") > 0)
            {
                Manager.Lua.luaNames.Add(info[0]);
            }
        }
    }
    IEnumerator LoadBundleAsync(string assetName/*资源名*/, Action<UObject> action = null/*完成回调*/)
    {
        string bundleName = m_BundleInfos[assetName].BundleName;
        string bundlePath = Path.Combine(PathUtil.BundleResourcePath, bundleName);
        List<string> depedences = m_BundleInfos[assetName].Dependences;

        BundleData bundle = GetBundle(bundleName);
        if (bundle == null)
        {
            UObject obj = Manager.Pool.Spawn("AssetBundle", bundleName);
            if (obj != null)
            {
                AssetBundle ab = obj as AssetBundle;
                bundle = new BundleData(ab);
            }
            else
            {
                AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(bundlePath);
                yield return request;
                bundle = new BundleData(request.assetBundle);
            }




            m_AssetBundles.Add(bundleName, bundle);
        }
        if (depedences.Count > 0 && depedences != null)
        {
            for (int i = 0; i < depedences.Count; i++)
            {
                yield return LoadBundleAsync(depedences[i]);//加载依赖资源不需要回调
            }
        }

        //场景资源不需要obj
        if (assetName.EndsWith(".unity"))
        {
            action?.Invoke(null);
            yield break;
        }
        if (action == null)
        {
            yield break;
        }
        AssetBundleRequest bundleRequest = bundle.Bundle.LoadAssetAsync(assetName);
        yield return bundleRequest;

        if (action != null && bundleRequest != null)
        {
            action.Invoke(bundleRequest.asset);
        }
    }
    BundleData GetBundle(string assetName)
    {
        BundleData bundle = null;
        if (m_AssetBundles.TryGetValue(assetName, out bundle))
        {
            bundle.Count++;
            return bundle;
        }
        return null;
    }
    private void MinusOneBundleCount(string bundleName)
    {
        if (m_AssetBundles.TryGetValue(bundleName, out BundleData bundle))
        {
            if (bundle.Count > 0)
            {
                bundle.Count--;
                Debug.Log("bundle引用计数:" + bundleName + "Count:" + bundle.Count);
            }
            if (bundle.Count <= 0)
            {
                Debug.Log("放入bundle对象池：" + bundleName);
                Manager.Pool.UnSpawn("AssetBundle", bundleName, bundle.Bundle);
                m_AssetBundles.Remove(bundleName);
            }
        }
    }
    public void MinusBundleCount(string assetName)
    {
        string bundleName = m_BundleInfos[assetName].BundleName;
        MinusOneBundleCount(bundleName);
        List<string> dependences = m_BundleInfos[assetName].Dependences;
        if (dependences != null)
        {
            foreach (string dependence in dependences)
            {
                string name = m_BundleInfos[dependence].BundleName;
                MinusOneBundleCount(name);
            }
        }
    }





#if UNITY_EDITOR
    /// <summary>
    /// 编辑器环境加载资源（减少打Bundle频率
    /// </summary>
    /// <param name="assetName"></param>
    /// <param name="action"></param>
    void EditorLoadAsset(string assetName, Action<UObject> action = null)
    {
        UObject obj = UnityEditor.AssetDatabase.LoadAssetAtPath(assetName, typeof(UObject));
        if (obj == null) Debug.LogError("Assets name is not exist:" + assetName);
        action?.Invoke(obj);
    }
#endif
    private void LoadAsset(string assetName, Action<UObject> action = null)
    {//协程的接口
#if UNITY_EDITOR
        if (AppConst.gameMode == GameMode.EditorMode)
        {
            EditorLoadAsset(assetName, action);
        }
        else
#endif
            StartCoroutine(LoadBundleAsync(assetName, action));
    }
    public void LoadUI(string assetName, Action<UObject> action = null)
    {
        LoadAsset(PathUtil.GetUIPath(assetName), action);
    }
    public void LoadMusic(string assetName, Action<UObject> action = null)
    {
        LoadAsset(PathUtil.GetMusicPath(assetName), action);
    }
    public void LoadSound(string assetName, Action<UObject> action = null)
    {
        LoadAsset(PathUtil.GetSoundPath(assetName), action);
    }
    public void LoadEffect(string assetName, Action<UObject> action = null)
    {
        LoadAsset(PathUtil.GetEffectPath(assetName), action);
    }
    public void LoadScene(string assetName, Action<UObject> action = null)
    {
        LoadAsset(PathUtil.GetScenePath(assetName), action);
    }

    public void LoadLua(string assetName, Action<UObject> action = null)
    {
        LoadAsset(assetName, action);
    }
    public void LoadPrefab(string assetName, Action<UObject> action = null)
    {
        LoadAsset(assetName, action);
    }

    public void UnloadBundle(UObject obj)
    {
        AssetBundle ab = obj as AssetBundle;
        ab.Unload(true);
    }


    //卸载待做


}
